#ifndef CSLLIST_H_
#define CSLLIST_H_

#ifndef NULL
#define NULL 0
#endif

template <typename Type> CSLLIter;

template <typename Type> CSLList
{
private:

	struct Node
	{
		Node* pNext;
		type  cInfo;
	};

	Node*	m_pFront;
	Node*	m_pEnd;
	int		m_nSize;

	
public:

	friend class CSLLIter<Type>;

	CSLList()
	{
		m_pFront = m_pEnd = NULL;
		m_nSize = 0;
	}

	~CSLList()
	{
		Clear();
	}

	CSLList(const CSLList& obj)
	{		
		if(this != &obj)
		{
			Clear();
			CopyList(this, obj);
		}
	}

	CSLList& operator=(const SCLList& obj)
	{
		if(this != &obj)
		{
			Clear();
			CopyList(this, obj);
		}

		return *this;
	}

	inline const int GetSize() { return m_nSize; }

	inline bool isEmpty() { return m_pFront == NULL; }

	Type& operator[](const int count)
	{
		if(isEmpty() || m_nSize < count)
			return NULL;


		CSLLIter<Type> iter(this);
		iter.Begin();
		for(int index = 0; index < count; index++, iter++) { }

		return iter.Current();
	}

	void Clear(void)
	{
		if(!isEmpty())
		{
			Node* pTemp = m_pFront;
			while(pTemp)
			{
				m_pFront = m_pFront->pNext;
				delete pTemp;
				pTemp = m_pFront;
			}
			m_pFront = m_pEnd = NULL;
		}

		m_nSize = 0;
	}

	void AddFront(const Type& obj)
	{
		if(isEmpty())
		{
			m_pFront = new Node*;
			m_pEnd = m_pFront;
			m_pFront->cInfo = obj;
			m_pFront->pNext = NULL;
		}
		else
		{
			Node* pTemp = new Node*;
			pTemp->pNext = m_pFront;
			pTemp->cInfo = obj;
			m_pFront = pTemp;
		}

		m_nSize++;
	}

	void AddEnd(const Type& obj)
	{
		if(isEmpty())
		{
			m_pFront = new Node*;
			m_pEnd = m_pFront;
			m_pFront->cInfo = obj;
			m_pFront->pNext = NULL;
		}
		else
		{
			Node* pTemp = new Node*;
			pTemp->pNext = NULL;
			pTemp->cInfo = obj;
			m_pEnd->pNext = pTemp;
			m_pEnd = pTemp;
		}
		m_nSize++;
	}

	void Insert(CSLLIter<Type>& index, const Type& obj)
	{
		if(isEmpty())
		{
			AddFront(obj);
		}
		else if(index == NULL)
		{
			return;
		}
		else
		{
			Node* pTemp = new Node*;
			pTemp->cInfo = obj;
			index.m_pPrev->pNext = pTemp;
			pTemp->pNext = index.m_pCur;
			index.m_pCur = pTemp;
			m_nSize++;
		}
	}

	void Remove(CSLLIter<Type>& index)
	{
		if(isEmpty() || index == NULL)
		{
			return;
		}
		else
		{
			Node* pTemp = index.m_pCur;
			index.m_pPrev->pNext = pTemp->pNext;
			pTemp->pNext = NULL;
			delete pTemp;
			pTemp = NULL;
			m_nSize--;
		}
	}

	void RemoveFront(void)
	{
		if(isEmpty())
			return;
		else if(m_nSize == 1)
		{
			delete m_pFront;
			m_pFront = m_pEnd = NULL;
		}
		else
		{
			Node* pTemp = m_pFront;
			m_pFront = pTemp->pNext;
			pTemp->pNext = NULL;
			delete pTemp;
			pTemp = NULL;
			m_nSize--;
		}
	}

	void RemoveEnd(void)
	{
		if(isEmpty())
			return;
		else if(m_nSize == 1)
		{
			delete m_pFront;
			m_pFront = m_pEnd = NULL;
		}
		else
		{
			CSLLIter<Type> iter(this);
			iter.Begin();
			while(iter.m_pCur->pNext != NULL)
			{
				iter++;
			}

			Node* pTemp = m_pEnd;
			m_pEnd = iter.m_pPrev;
			m_pEnd->pNext = NULL;
			delete pTemp;
		}
	}


private:
	void CopyList(CSLList& dest, CSLList& source)
	{
		if(!source.isEmpty())
		{
			for(int index = 0; index < source.GetSize(); index++)
			{
				dest.AddEnd(source[index]);
			}
		}
	}
};


template <typename Type>
class CSLLIter
{
private:

	typename CSSList<Type>::Node*	m_pCur;
	typename CSLList<Type>::Node*	m_pPrev;
	CSLList<Type>*					m_cList;

public:
	friend class CSSList<Type>;

	CSLLIter(CSLList<Type>& list)
	{
		m_cList = &list;
		m_pPrev = NULL;
		m_pCur = NULL;
	}

	void Begin(void)
	{
		m_pCur = list->m_pFront;
		m_pPrev = NULL;
	}

	bool End(void) const
	{
		return m_pCur == NULL;
	}

	CSLLIter<Type>& operator++()
	{
		if(m_pCur)
		{
			m_pPrev = m_pCur;
			m_pCur = m_pCur->pNext;
		}
		return *this;
	}

	Type& GetCurrent(void) const
	{
		if(m_pCur)
		{
			return m_pCur->cInfo;
		}
		return NULL;
	}
};

#endif